//
//  ICWKLoadManager.swift
//  ICWKWebview
//
//  Created by cc on 2018/7/23.
//  Copyright © 2018年 cc. All rights reserved.
//

import UIKit
import WebKit
protocol ICWKDelegate: class {
    func setupWebTitle(_ webview: WKWebView, _ title: String)
    func ic_goBack(_ webview: WKWebView)
    func presentAler(_ webview: WKWebView, _ alert: UIAlertController)
}

class ICWKLoadManager: NSObject {
    //不设置 不判断内部加载，还是跳出使用浏览器加载
    public var HostUrl: String?
    public var wkWebV : WKWebView!
    private let userController = WKUserContentController()
    private var crossDomain = false
    //注册交互方法集
    private var handleNames: [String] = []
    public var delegate: ICWKDelegate?
    lazy var ic_script: ICWKScriptDelegate = {
        let script = ICWKScriptDelegate()
        script.delegate = self
        return script
    }()
    lazy var progressV: UIProgressView = {
        let proV = UIProgressView()
        proV.tintColor = .blue
        //        proV.trackTintColor = .white
        wkWebV.addSubview(proV)
        return proV
    }()
    
    override init() {
        super.init()
        addWKWebView()
    }
    
    public func registerWebHandle(_ names: [String]) {
        for name in names {
            userController.add(ic_script, name: name)
        }
        handleNames = names
    }
    
    public func registerWebHandle(_ name: String) {
        userController.add(ic_script, name: name)
        handleNames.append(name)
    }
    
    private func unregisterWebHandle() {
        for name in handleNames {
            userController.removeScriptMessageHandler(forName: name)
        }
    }
    
    public func loadHtml(_ urlStr: String) {
        loadHtml(urlStr, nil)
    }
    
    public func loadHtml(_ urlStr: String, _ parm: [String: Any]?) {
        var urlStr = urlStr
        var request: URLRequest?
        if urlStr.hasPrefix("http") {
            if let url = URL(string: urlStr) {
                request = getRequestForCookie(url)
            }
        }else {
            //本地html
            var path = Bundle.main.path(forResource: urlStr, ofType: "html")
            let parmStr = getPramStr(parm)
            if path != nil {
                var url: URL?
                url = URL(fileURLWithPath: path!)
                if parmStr.count > 0 {
                    if url != nil {
                        path = url!.absoluteString + parmStr
                    }
                    url = URL(string: path!)
                }
                if url != nil {
                    request = getRequestForCookie(url!)
                }
                
            }else if (HostUrl != nil) {
                urlStr = HostUrl! + urlStr
                if let url = URL(string: urlStr) {
                    request = getRequestForCookie(url)
                }
            }
            
        }
        if request != nil {
            wkWebV.load(request!)
        }else {
            print("传值有误")
        }
    }
    
    private func getPramStr(_ dict: [String: Any]?) -> String {
        var parmStr = ""
        if dict != nil {
            for (key, value) in dict! {
                let str = "&" + key + "=" + String(describing: value)
                parmStr += str
            }
            let fromIndex = parmStr.index(parmStr.startIndex, offsetBy: 1)
            parmStr = "?" + parmStr.suffix(from: fromIndex)
        }
        return parmStr
    }
    
    //第一次request 手动添加cookie
    private func getRequestForCookie(_ url: URL)-> URLRequest {
        var request = URLRequest(url: url)
        let cookieJar = HTTPCookieStorage.shared
        var cookieStr = ""
        if let cookies = cookieJar.cookies {
            for cookie in cookies {
                cookieStr += cookie.name + "=" + cookie.value + ";"
            }
            if cookieStr.count > 0 {
                cookieStr.remove(at: cookieStr.endIndex)
            }
        }
        request.addValue(cookieStr, forHTTPHeaderField: "Cookie")
        return request
    }
    
    private func addWKWebView() {
        let config = WKWebViewConfiguration()
        config.preferences = WKPreferences()
        config.preferences.minimumFontSize = 20
        config.preferences.javaScriptEnabled = true
        config.preferences.javaScriptCanOpenWindowsAutomatically = true
        config.userContentController = userController
        
        wkWebV = WKWebView(frame: .zero, configuration: config)
        
        wkWebV.navigationDelegate = self
        wkWebV.uiDelegate = self
        
        
        wkWebV.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: nil)
        wkWebV.addObserver(self, forKeyPath: "title", options: .new, context: nil)
        
       
        
    }
    
    
    @objc func selForJsTest() {
        print("厉害")
    }

    
    func ic_webback() {
        delegate?.ic_goBack(wkWebV)
    }
    
    deinit {
        unregisterWebHandle()
        wkWebV.removeObserver(self, forKeyPath: "estimatedProgress")
        wkWebV.removeObserver(self, forKeyPath: "title")
        print("释放\(self.classForCoder)")
    }
    
    
    //页面跳转手动注入cookie
    func htmlSkipAddCookie() {
        let cookieStorage = HTTPCookieStorage.shared
        let jsFuncStr = "function setCookie(name,value,expires) { var oDate=new Date(); oDate.setDate(oDate.getDate()+expires); document.cookie=name+'='+value+';expires='+oDate+';path=/' } function getCookie(name) { var arr = document.cookie.match(new RegExp('(^| )'+name+'=([^;]*)(;|$)')); if(arr != null) return unescape(arr[2]); return null; } function delCookie(name) { var exp = new Date(); exp.setTime(exp.getTime() - 1); var cval=getCookie(name); if(cval!=null) document.cookie= name + '='+cval+';expires='+exp.toGMTString(); }"
        
        var jsCookieStr = jsFuncStr
        for cookie in cookieStorage.cookies! {
            let excuteJsStr = "setCookie(" + cookie.name + "," + cookie.value + "," + "1);"
            jsCookieStr += excuteJsStr
        }
        wkWebV.evaluateJavaScript(jsCookieStr, completionHandler: nil)
    }
    
    
    //监听
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if let obj = object as? WKWebView, obj == wkWebV {
            if keyPath == "estimatedProgress" {
                if let changeDic = change, let newProgress = changeDic[.newKey] as? Float {
                    print(newProgress)
                    progressV.setProgress(newProgress, animated: true)
                    if progressV.progress >= 1.0 {
                        DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
                            self.progressV.isHidden = true
                            self.progressV.setProgress(0, animated: false)
                        })
                    }else {
                        progressV.isHidden = false
                        
                    }
                }
            }else if keyPath == "title" {
                if let changeDic = change, let title = changeDic[.newKey] as? String {
                    delegate?.setupWebTitle(wkWebV, title)
                }
            }
            
            
        }
    }
}

extension ICWKLoadManager: WKNavigationDelegate, WKUIDelegate {
    //MARK: navigationDelegate
    // 页面开始加载时调用
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        //        showHud(wkWebV)
    }
    // 当内容开始返回时调用
    func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
        
    }
    // 页面加载完成之后调用
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        // 页面内跳转 需要注入cookie
        htmlSkipAddCookie()
        
        //        dismissHud(wkWebV)
    }
    // 页面加载失败时调用
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        //        dismissHud(wkWebV)
    }
    
    // 接收到服务器跳转请求之后调用
    func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
        
    }
    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
        
    }
    //接收到服务器跳转请求之后调用
    func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        
        if challenge.protectionSpace.authenticationMethod  == NSURLAuthenticationMethodServerTrust {
            if challenge.previousFailureCount == 0 {
                let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
                completionHandler(.useCredential, credential)
            }else {
                completionHandler(.cancelAuthenticationChallenge, nil)
            }
        }else {
            completionHandler(.cancelAuthenticationChallenge, nil)
        }
        
    }
    
    
    
    //在发送请求之前，决定是否跳转
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        let hostName = navigationAction.request.url?.absoluteString
        if HostUrl == nil {
            decisionHandler(.allow)
            return
        }
        if hostName?.contains(HostUrl!) == false, hostName?.hasPrefix("http") == true {
            // 对于跨域，需要手动跳转
            if #available(iOS 10.0, *) {
                UIApplication.shared.open(navigationAction.request.url!, options: [:], completionHandler: { finished in
                    if finished { self.ic_webback() }
                })
            } else {
                // Fallback on earlier versions
                UIApplication.shared.openURL(navigationAction.request.url!)
                DispatchQueue.main.asyncAfter(deadline: .now() + 1, execute: {
                    self.ic_webback()
                })
            }
            
            decisionHandler(.cancel)
        } else {
            
            decisionHandler(.allow)
        }
        
    }
    //在响应完成时，调用的方法。如果设置为不允许响应，web内容就不会传过来
    func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) {
        decisionHandler(.allow)
    }
    
    //MARK: WKUIDelegate
    //alert 警告框
    func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) {
        let alert = UIAlertController(title: "警告", message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in
            completionHandler()
        }))
        delegate?.presentAler(webView, alert)
    }
    
}

extension ICWKLoadManager: ICWKScriptProtocol {
    func performSel(_ name: String, parm: Any) {
        let sel = NSSelectorFromString(name + ":")
        if responds(to: sel){
            perform(sel, with: parm)
        }
    }
    
    
}
